package com.wjk.easy.blue;

import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.content.Intent;
import android.hardware.Sensor;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

import com.clj.fastble.callback.BleGattCallback;
import com.clj.fastble.callback.BleNotifyCallback;
import com.clj.fastble.callback.BleReadCallback;
import com.clj.fastble.data.BleDevice;
import com.clj.fastble.exception.BleException;
import com.wjk.easy.EasyApplication;
import com.wjk.easy.blue.rd915demo.BTClient;
import com.wjk.easy.utils.CommonUtil;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;

public class FastBleService extends Service {
    private final static String TAG = FastBleService.class.getSimpleName();
    private List<Sensor> mEnabledSensors = new ArrayList<Sensor>();
    private BluetoothManager mBluetoothManager;
    private BluetoothAdapter mBluetoothAdapter;
    private String mBluetoothDeviceAddress;
    private BluetoothGatt mUhfGatt;
    private BleDevice mUhfDevice;
    private int mConnectionState = STATE_DISCONNECTED;
    private static final int STATE_DISCONNECTED = 0;
    private static final int STATE_CONNECTING = 1;
    private static final int STATE_CONNECTED = 2;

    public final static String ACTION_GATT_CONNECTED =
            "com.example.bluetooth.le.ACTION_GATT_CONNECTED";
    public final static String ACTION_GATT_DISCONNECTED =
            "com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
    public final static String ACTION_GATT_SERVICES_DISCOVERED =
            "com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
    public final static String ACTION_DATA_AVAILABLE =
            "com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
    public final static String EXTRA_DATA =
            "com.example.bluetooth.le.EXTRA_DATA";
    public static final String DEVICE_TYPE_UHF = "BLUE_UHF";
    public static final String DEVICE_TYPE_WEIGHT = "BLUE_WIGHT";


    FastBleDeviceManager fastBleDeviceManager;
    private HashMap<String, String> typeMap = new HashMap<>();

    @Override
    public void onCreate() {
        super.onCreate();
        fastBleDeviceManager = new FastBleDeviceManager();
        fastBleDeviceManager.setConnectStateListener(new BlueConnectListener());
        typeMap.put(DEVICE_TYPE_UHF, "读卡器");
        typeMap.put(DEVICE_TYPE_WEIGHT, "电子称");
    }

    BluetoothGattCharacteristic bluetoothGattCharacteristic;
    public class BlueConnectListener extends BleGattCallback {
        private String deviceType;
        @Override
        public void onStartConnect() {
            if (typeMap.get(deviceType) != null) {
                mainEventListener.showMsg("开始连接" + typeMap.get(deviceType));
            }
        }
        @Override
        public void onConnectFail(BleDevice bleDevice, BleException exception) {
            if (typeMap.get(deviceType) != null) {
                mainEventListener.showMsg(typeMap.get(deviceType) + "连接失败，请重试");
            }
        }
        @Override
        public void onConnectSuccess(BleDevice bleDevice, BluetoothGatt gatt, int status) {
            mainEventListener.onConnectSuccess(deviceType);
            mUhfGatt = gatt;
            mUhfDevice = bleDevice;
            String name = bleDevice.getName();
            String mac = bleDevice.getMac();
            CommonUtil.setSpValue(EasyApplication.getAppContext(),mac,deviceType);
            Log.e(TAG,"connect success,name: "+name+" mac: "+mac);
            for (BluetoothGattService service : gatt.getServices()) {
                String uuid = service.getUuid().toString();
                if(uuid.equals("0000ffe0-0000-1000-8000-00805f9b34fb")){
                    bluetoothGattCharacteristic = service.getCharacteristics().get(0);
                    Log.e(TAG,"get target bluetoothGattCharacteristic");
                    break;
                }
            }
        }

        @Override
        public void onDisConnected(boolean isActiveDisConnected, BleDevice device, BluetoothGatt gatt, int status) {
            mainEventListener.onDeviceDisconnect(device);
        }

        public void setDeviceType(String deviceType) {
            this.deviceType = deviceType;
        }
    }



    public class LocalBinder extends Binder {
        Map<String, Integer> scanResult = new HashMap<String, Integer>();
        Map<String, byte[]> epcBytes = new HashMap<String, byte[]>();
        public FastBleService getService() {
            return FastBleService.this;
        }
        public FastBleDeviceManager getBlueDeviceManager() {
            return fastBleDeviceManager;
        }

        public void setConnectEvent(OuterConnectStateListener event) {
            mainEventListener = event;
        }
        public void startScanCard() {
            if(bluetoothGattCharacteristic!=null){
                /*BTUhfClient.bluetoothGattCharacteristic=bluetoothGattCharacteristic;
                BTUhfClient.targetUhfGatt=mUhfGatt;
                BTClient.bluetoothGattCharacteristic=bluetoothGattCharacteristic;
                BTClient.targetUhfGatt=mUhfGatt;*/

                mUhfGatt.setCharacteristicNotification(bluetoothGattCharacteristic, true);

                BluetoothGattDescriptor clientConfig =
                        bluetoothGattCharacteristic.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));

                if (true) {
                    clientConfig.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                } else {
                    clientConfig.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
                }
                mUhfGatt.writeDescriptor(clientConfig);

                EasyApplication.getBluetoothClient().notify(
                        EasyApplication.getBluetoothClient().convertBleDevice(mUhfGatt.getDevice()),
                        "0000ffe0-0000-1000-8000-00805f9b34fb",
                        bluetoothGattCharacteristic.getUuid().toString(),
                        new BleNotifyCallback() {
                            @Override
                            public void onNotifySuccess() {
                                Log.e("wjk","onNotifySuccess:");
                            }

                            @Override
                            public void onNotifyFailure(BleException exception) {
                                Log.e("wjk","onNotifyFailure:"+ exception.getDescription());
                            }

                            @Override
                            public void onCharacteristicChanged(byte[] data) {
                                String recv=BTClient.bytesToHexString(data, 0, data.length);
                                Log.e("wjk","onCharacteristicChanged:"+ recv);
                            }
                        });
                Timer timer = new Timer();
                timer.schedule(new TimerTask() {
                    @Override
                    public void run() {
                        readuid();
                        Set<String> epcSets = scanResult.keySet();
                        if(!epcSets.isEmpty()){
                            Log.e("wjk","scanResult:"+ epcSets.iterator().next());
                        }
                    }
                }, 0, 20);
            }
        }

        private void readuid() {
            String[] lable = ScanUID();
            if (lable == null) {
                return;
            }
            for (String key : lable) {
                if (key == null || key.equals("")) return;
                int num = scanResult.get(key) == null ? 0 : scanResult.get(key);
                scanResult.put(key, num + 1);
            }
        }

        public int errorcount = 0;

        public String[] ScanUID(){
            byte[] EPCList = new byte[5000];
            int[] CardNum = new int[2];
            int[] EPCLength = new int[2];
            int result = BTClient.Inventory_G2((byte) 4, (byte) 0, (byte) 0, (byte) 0, (byte) 0, CardNum, EPCList, EPCLength);
            if (((CardNum[0] & 255) > 0) && (result != 0x30)) {
                int Scan6CNum = CardNum[0] & 255;
                String[] lable = new String[Scan6CNum];
                StringBuffer bf;
                int j = 0, k;
                String str;
                byte[] epc;
                Log.i("zdy", "num = " + Scan6CNum + ">>>>>>" + "len = " + EPCLength[0]);
                for (int i = 0; i < Scan6CNum; i++) {
                    bf = new StringBuffer("");
                    Log.i("yl", "length = " + EPCList[j]);
                    epc = new byte[EPCList[j] & 0xff];
                    for (k = 0; k < (EPCList[j] & 0xff); k++) {
                        str = Integer.toHexString(EPCList[j + k + 1] & 0xff);
                        if (str.length() == 1) {
                            bf.append("0");
                        }
                        bf.append(str);
                        epc[k] = EPCList[j + k + 1];
                    }
                    lable[i] = bf.toString().toUpperCase();
                    epcBytes.put(lable[i], epc);
                    j = j + k + 2;
                }
                return lable;
            }
            return null;
        }
    }

    OuterConnectStateListener mainEventListener;

    public interface OuterConnectStateListener {
        void showMsg(String msg);

        void onDeviceDisconnect(BleDevice device);

        void onConnectSuccess(String deviceType);
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG,"==============service onBind===============");
        return new LocalBinder();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.e(TAG,"==============service onUnbind===============");
        close();
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        Log.e(TAG,"==============service destroy===============");
        super.onDestroy();
    }

    /**
     * After using a given BLE device, the app must call this method to ensure resources are
     * released properly.
     */
    public void close() {
        if (mUhfGatt == null) {
            return;
        }
        mUhfGatt.close();
        mUhfGatt = null;
    }
}
